const app = require('j7/app');
const utils = require('j7/utils');
const bcutils = require('j7/bcutils');
const sync = require("j7/sync");
const log = require("j7/log");
const metaFactory = require('../metadata/factory');
const bcClass = require('../blockchain');
const BaseService = require('./baseservice');

const netIdHash = {};

function getBc(netId) {
  return utils.hasKey(netIdHash, netId) ? netIdHash[netId] : null;
}

class BlockChain extends BaseService {

  #bc = null;

  static async staticInit() {
    metaFactory.getNetList().forEach(async (net) => {
      const bc = new bcClass(net['netId']);
      netIdHash[net['netId']] = bc;
      await bc.init();
    });
  }

  init(netId) {
    this.#bc = getBc(netId);
    return this.#bc != null;
  }

  async mustBeActive() {
    await this.#bc.mustBeActive();
  }

  getNetId() {
    return this.#bc.getNetId();
  }

  getCurrBlockNumber() {
    return this.#bc.getCurrBlockNumber();
  }

  async lockQuery() {
    await this.#bc.lockQuery();
  }

  async unlockQuery() {
    await this.#bc.unlockQuery();
  }

  isAddress(address) {
    return this.#bc.isAddress();
  }

  getContractAddressByName(name) {
    const contract = this.#bc.getContractByName(name);
    return contract ? bcutils.toNormalAddress(contract['address']) : '';
  }

  async getPastEvents(contractName, eventName, ...args) {
    return await this.#bc[contractName + 'Instance'].getPastEvents(eventName, ...args);
  }

  async ownerOf721(contractName, tokenId) {
    return await this.#bc[contractName + 'Instance'].methods.ownerOf(tokenId).call();
  }

  async getBlockData(blockNumber) {
    return await this.#bc.getBlockData(blockNumber);
  }

}

module.exports = BlockChain;
